package com.ziki.kwdj.biz;

import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.imageio.ImageIO;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.Header;
import org.apache.http.HttpHost;
import org.apache.http.NameValuePair;
import org.apache.http.client.CookieStore;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.DefaultProxyRoutePlanner;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ziki.kwdj.model.ClassInfo;
import com.ziki.kwdj.model.Info;

public class ViewClass {
    private static Logger log = LoggerFactory.getLogger(ViewClass.class);
    private CloseableHttpClient httpclient;
    private HttpClientContext context;
    private Map<String, String> mapHeaders;
    private Map<String, Info> mapInfo;
    private CookieStore cookieStore;

    @SuppressWarnings("unused")
    public ViewClass() {
        mapInfo = new HashMap<String, Info>();
        context = HttpClientContext.create();

        RequestConfig config = RequestConfig.custom().setCookieSpec(CookieSpecs.STANDARD).build();

        HttpHost proxy = new HttpHost("10.113.253.11", 808);
        DefaultProxyRoutePlanner routePlanner = new DefaultProxyRoutePlanner(proxy);
        cookieStore = new BasicCookieStore();
        this.httpclient = HttpClients.custom() //
                // .setRoutePlanner(routePlanner) //
                .setDefaultRequestConfig(config) //
                .setDefaultCookieStore(cookieStore).build();
        mapHeaders = new HashMap<String, String>();
        mapHeaders.put("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:37.0) Gecko/20100101 Firefox/37.0");
        mapHeaders.put("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
        mapHeaders.put("Accept-Language", "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3");
        mapHeaders.put("Accept-Encoding", "gzip, deflate");
        mapHeaders.put("DNT", "1");
        mapHeaders.put("Host", "www.kwdj.gov.cn");
    }

    /**
     * 取得验证码
     * 
     * @return
     */
    public BufferedImage getCodeNubImg() {
        StringBuffer sb = new StringBuffer();
        sb.append("http://www.kwdj.gov.cn/CodeNubImg.aspx");

        HttpGet httpGet = new HttpGet(sb.toString());
        httpGet.setHeaders(getCommonHeaders());
        httpGet.setHeader("Referer", "http://www.kwdj.gov.cn/ClassAction/Default.aspx?alpe=0");

        CloseableHttpResponse response = null;
        try {
            response = httpclient.execute(httpGet, context);
            if (response.getStatusLine().getStatusCode() != 200) {
                return null;
            }
            return ImageIO.read(response.getEntity().getContent());
        } catch (Exception e) {
            log.error("Exception", e);
        } finally {
            close(response);
        }
        return null;
    }

    /**
     * 登录
     * 
     * @param info
     * @return
     */
    public String login(Info info) {
        StringBuffer sb = new StringBuffer();
        sb.append("http://www.kwdj.gov.cn/CommonHandler.ashx?typeid=1");
        sb.append("&LoginLGName=").append(info.getUserName());
        sb.append("&LoginPWD=").append(info.getPassword());
        sb.append("&LoginCode=").append(info.getCode());

        HttpGet httpGet = new HttpGet(sb.toString());
        httpGet.setHeaders(getCommonHeaders());
        httpGet.setHeader("Referer", "http://www.kwdj.gov.cn/ClassAction/Default.aspx?alpe=0");

        CloseableHttpResponse response = null;
        try {
            response = httpclient.execute(httpGet, context);
            if (response.getStatusLine().getStatusCode() != 200) {
                return null;
            }
            // for (Header header : response.getHeaders("Set-Cookie")) {
            // HeaderElement[] el = header.getElements();
            // String cookieValue = "";
            // for (HeaderElement e : el) {
            // System.out.println(e.getName() + "\t" + e.getValue());
            // if (e.getName().equals("ASP.NET_SessionId") ||
            // e.getName().equals("safedog-flow-item")) {
            // cookieValue += e.getName() + "=" + e.getValue() + ";";
            // }
            // }
            // mapHeaders.put("Cookie", cookieValue);
            // }
            return EntityUtils.toString(response.getEntity());
        } catch (Exception e) {
            log.error("Exception", e);
        } finally {
            close(response);
        }
        return "";
    }

    /**
     * 退出
     * 
     * @return
     */
    public String logout() {
        StringBuffer sb = new StringBuffer();
        sb.append("http://www.kwdj.gov.cn/LoginOut.aspx");

        HttpGet httpGet = new HttpGet(sb.toString());
        httpGet.setHeaders(getCommonHeaders());
        httpGet.setHeader("Referer", "http://www.kwdj.gov.cn/ClassAction/Default.aspx?alpe=0");

        CloseableHttpResponse response = null;
        try {
            response = httpclient.execute(httpGet, context);
            return EntityUtils.toString(response.getEntity());
        } catch (Exception e) {
            log.error("Exception", e);
        } finally {
            close(response);
        }
        return "";
    }

    /**
     * 提交课程
     * 
     * @param info
     * @return
     */
    public String check(Info info) {
        if (info == null) {
            return "课程信息Info=null";
        }
        if (StringUtils.isEmpty(info.getInfoID())) {
            return "课程信息InfoID=null";
        }
        if (StringUtils.isEmpty(info.getUserID())) {
            return "课程信息UserID=null";
        }
        if (StringUtils.isEmpty(info.getSessionID())) {
            return "课程信息SessionID=null";
        }
        HttpPost httpPost = new HttpPost("http://www.kwdj.gov.cn/ClassAction/ClassActionHandler.ashx?typeID=0");

        httpPost.setHeaders(getCommonHeaders());
        httpPost.setHeader("Accept", "text/plain, */*; q=0.01");
        httpPost.setHeader("Cache-Control", "no-cache");
        httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
        httpPost.setHeader("Pragma", "no-cache");
        httpPost.setHeader("X-Requested-With", "XMLHttpRequest");
        httpPost.setHeader("Referer",
                "http://www.kwdj.gov.cn/ClassAction/ViewClassPage.aspx?aple=yes&classID=" + info.getClassID());
        List<NameValuePair> nvps = new ArrayList<NameValuePair>();
        nvps.add(new BasicNameValuePair("infoID", info.getInfoID()));
        nvps.add(new BasicNameValuePair("userID", info.getUserID()));
        nvps.add(new BasicNameValuePair("sessionID", info.getSessionID()));
        nvps.add(new BasicNameValuePair("nowTime", String.valueOf(info.getNowTime())));

        CloseableHttpResponse response = null;
        try {
            httpPost.setEntity(new UrlEncodedFormEntity(nvps));
            response = httpclient.execute(httpPost, context);
            if (response.getStatusLine().getStatusCode() != 200) {
                return null;
            }
            return EntityUtils.toString(response.getEntity());
        } catch (Exception e) {
            log.error("Exception", e);
        } finally {
            close(response);
        }
        return null;
    }

    /**
     * 取得课程信息
     * 
     * @param classId
     * @return
     */
    public Info getClassInfo(String classId) {
        log.info("************************getClassInfo:{}", classId);
        StringBuffer sb = new StringBuffer();
        sb.append("http://www.kwdj.gov.cn/ClassAction/ViewClassPage.aspx?alpe=yes");
        sb.append("&classID=").append(classId);
        HttpGet httpGet = new HttpGet(sb.toString());
        httpGet.setHeaders(getCommonHeaders());
        httpGet.setHeader("Referer", "http://www.kwdj.gov.cn/ClassAction/View.aspx?alpe=0&infoID=" + classId);

        CloseableHttpResponse response = null;
        try {
            response = httpclient.execute(httpGet, context);
            if (response.getStatusLine().getStatusCode() != 200) {
                return null;
            }
            Info info = JsoupParser.parseInfo(response.getEntity().getContent());
            info.setClassID(classId);
            return info;
        } catch (Exception e) {
            log.error("Exception", e);
        } finally {
            close(response);
        }
        return null;
    }

    /**
     * 查看课程
     * 
     * @param classId
     * @return
     */
    public void view(String classId) {
        log.info("************************view class:{}", classId);
        StringBuffer sb = new StringBuffer();
        sb.append("http://www.kwdj.gov.cn/ClassAction/View.aspx?alpe=0");
        sb.append("&infoID=").append(classId);
        HttpGet httpGet = new HttpGet(sb.toString());
        httpGet.setHeaders(getCommonHeaders());
        httpGet.setHeader("Referer", "http://www.kwdj.gov.cn/ClassAction/Default.aspx?alpe=0");

        CloseableHttpResponse response = null;
        try {
            response = httpclient.execute(httpGet, context);
        } catch (Exception e) {
            log.error("Exception", e);
        } finally {
            close(response);
        }
    }

    /**
     * 取得课程信息
     * 
     * @param classType
     *            1:必学 2:选学 3:自学
     * @return
     */
    public Info getClassInfoList(String classType) {
        log.info("************************get class list: type {}", classType);
        Info info = mapInfo.get(classType);
        if (info == null) {
            info = getClassesFromSite(classType);
            mapInfo.put(classType, info);
        }
        return info;
    }

    /**
     * 从网站取得课程列表
     * 
     * @param classType
     *            1:必学 2:选学 3:自学
     * @return
     */
    private Info getClassesFromSite(String classType) {
        Info info = null;
        StringBuffer sb = new StringBuffer();
        sb.append("http://www.kwdj.gov.cn/ClassAction/List.aspx?alpe=0");
        sb.append("&ClassTypeID=").append(classType);
        HttpGet httpGet = new HttpGet(sb.toString());
        httpGet.setHeaders(getCommonHeaders());
        httpGet.setHeader("Referer", "http://www.kwdj.gov.cn/ClassAction/Default.aspx?alpe=0");

        CloseableHttpResponse response = null;
        try {
            response = httpclient.execute(httpGet, context);
            if (response.getStatusLine().getStatusCode() != 200) {
                return null;
            }
            // 分析该当类型的首页课程信息
            info = JsoupParser.parseClassInfoList(response.getEntity().getContent());
            if (info != null) {
                // 取得首页的未学完的课程列表
                List<ClassInfo> lstClassInfo = info.getClassInfoStack();
                // 首页已学完
                if (lstClassInfo == null || lstClassInfo.isEmpty()) {
                    log.info("the first page has no data");
                    // 从最后一面开始学习
                    for (int i = info.getMaxPage(); i > 1; i--) {
                        sb = new StringBuffer();
                        sb.append("http://www.kwdj.gov.cn/ClassAction/List.aspx?alpe=0");
                        sb.append("&pn=").append(i);
                        sb.append("&orderType=1");
                        sb.append("&CateID=-1");
                        sb.append("&ClassTypeID=").append(classType);
                        sb.append("&KeyWord=");
                        httpGet = new HttpGet(sb.toString());
                        // URI uri = new
                        // URIBuilder().setScheme("http").setHost("www.kwdj.gov.cn")
                        // .setPath("/ClassAction/List.aspx").setParameter("alpe",
                        // "0").setParameter("pn", i + "")
                        // .setParameter("orderType",
                        // "1").setParameter("CateID", "-1")
                        // .setParameter("ClassTypeID",
                        // classType).setParameter("KeyWord", "").build();
                        // httpGet.setURI(uri);
                        httpGet.setHeaders(getCommonHeaders());
                        httpGet.setHeader("Referer", "http://www.kwdj.gov.cn/ClassAction/Default.aspx?alpe=0");
                        response = httpclient.execute(httpGet, context);
                        if (response.getStatusLine().getStatusCode() != 200) {
                            break;
                        }
                        // 分析该当类型的首页课程信息
                        info = JsoupParser.parseClassInfoList(response.getEntity().getContent());
                        // 该页有未学完的课程时退出
                        if (info != null && info.getClassInfoStack() != null && !info.getClassInfoStack().isEmpty()) {
                            break;
                        }
                        log.info("page {} has no data", i);
                    }
                }
            }
        } catch (Exception e) {
            log.error("Exception", e);
        } finally {
            close(response);
        }
        return info;
    }

    private Header[] getCommonHeaders() {
        Header[] headers = new BasicHeader[mapHeaders.size()];
        int i = 0;
        for (String key : mapHeaders.keySet()) {
            headers[i++] = new BasicHeader(key, mapHeaders.get(key));
        }
        return headers;
    }

    private void close(CloseableHttpResponse response) {
        try {
            if (response != null) {
                response.close();
            }
        } catch (IOException e) {
            log.error("Exception", e);
        }
    }

    public Map<String, String> getMapHeaders() {
        return mapHeaders;
    }

    public void setMapHeaders(Map<String, String> mapHeaders) {
        this.mapHeaders = mapHeaders;
    }
}
